﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.IO;

namespace Communication.Tcp
{
    class TaskAlreadyExistsException : Exception
    {
    }

    /// <summary>
    /// Factory for IOCP Tasks
    /// </summary>
    class TaskFactory
    {
        #region Ctor
        public TaskFactory()
        {
            this.m_tasks = new List<Task>();
        }
        #endregion

        #region Privates
        private bool isTaskExists(Task new_task)
        {
            foreach (Task task in m_tasks)
            {
                if (task.Equals(new_task))
                {
                    return true;
                }
            }
            return false;
        }
        #endregion

        #region Methods

        /// <summary>
        /// Revoke a task
        /// </summary>
        /// <param name="task">The task to revoke</param>
        public void RemoveTask(Task task)
        {
            this.m_tasks.Remove(task);
        }

        /// <summary>
        /// Generate new DataTask
        /// </summary>
        /// <param name="type">Task's type</param>
        /// <param name="client">Invoking client</param>
        /// <param name="data">Data</param>
        /// <returns>new DataTask</returns>
        public DataTask GenerateNewDataTask(WorkType type, TcpClient client, BufferedStream data)
        {
            // TODO: Duplication of code? try refactoring.
            DataTask new_task = new DataTask(type, client, this, data);
            if (!isTaskExists(new_task))
            {
                m_tasks.Add(new_task);
                return new_task;
            }
            else
            {
                throw new TaskAlreadyExistsException();
            }
        }

        /// <summary>
        /// Generate new Task
        /// </summary>
        /// <param name="type">Task's type</param>
        /// <param name="client">Invoking client</param>
        /// <returns>new Task</returns>
        public Task GenerateNewTask(WorkType type, TcpClient client)
        {
            Task new_task = new Task(type, client, this);
            if (!isTaskExists(new_task))
            {
                m_tasks.Add(new_task);
                return new_task;
            }
            else
            {
                throw new TaskAlreadyExistsException();
            }
        }

        /// <summary>
        /// Generate new task without client
        /// </summary>
        /// <param name="type">Task's type</param>
        /// <returns>new Task</returns>
        public Task GenerateNewTask(WorkType type)
        {
            return GenerateNewTask(type, null);
        }
        #endregion

        #region Fields
        private List<Task> m_tasks;
        #endregion 
    }
}
